AddCSLuaFile("cl_init.lua") 
AddCSLuaFile("shared.lua") 
include('shared.lua')


//****************************************************
//* Initalize function for the camera
function ENT:Initialize() 

	self.BaseClass.Initialize(self,Model("models/dav0r/camera.mdl"))
	
	//Create tangent control grips
	local gripA = ents.Create( "path_grip" )
	if(gripA and gripA:IsValid()) then
		gripA:Spawn()
		gripA:SetPos(self:GetPos() + Vector(0,10,0))
		gripA:SetParentNode(self)
	end
	self:SetNWEntity(ID_PATH_DIRECTION_ENTITY_A, gripA)

	local gripB = ents.Create( "path_grip" )
	if(gripB and gripB:IsValid()) then
		gripB:Spawn()
		gripB:SetPos(self:GetPos() - Vector(0,10,0))
		gripB:SetParentNode(self)
	end
	self:SetNWEntity(ID_PATH_DIRECTION_ENTITY_B, gripB)
	

	self:SetNWVector(ANICAM_DIR, Vector(20,0,0))
	self:SetNWVector(ANICAM_POS, Vector(20,0,0))

	//Create the control grips
	local rotationGrip = ents.Create( "path_grip" )
	if(rotationGrip and rotationGrip:IsValid()) then
		rotationGrip:Spawn()
		rotationGrip:SetPos(self:GetPos() + (50 * self:GetForward()))
		rotationGrip:SetParentNode(self)
	end
	self:SetNWEntity(ANICAM_ROTGRIP, rotationGrip)

	self:SetNWInt(ANICAM_SELECTED, 0)
	self:SetNWInt(ANICAM_RANGESELECTED, 0)
	self:SetNWInt(ANICAM_SHOWTRACK, 1)
	self:SetNWInt(ANICAM_SHOWDIRECTION, 1)
	self:SetNWInt(ANICAM_SHOWCAMERAID, self.BaseClass.GetRootNode(self):EntIndex())
	self:SetNWInt(ANICAM_SHOWTANGENTS, 1)
	self:SetNWFloat(ANICAM_ZOOM, 70.0)
	self:SetNWFloat(ANICAM_SHAKEAGRESSION, 0.0)
	self:SetNWFloat(ANICAM_SHAKEFREQUENCY, 0.0)
	self:SetNWFloat(ANICAM_TIMETRANSITION, 5.0)
	self:SetNWFloat(ANICAM_TIMESTOP, 0.0)
		  
	self:SetNWInt(ANICAM_PREVIEWSTATE, 0)
	self:SetNWBool(ANICAM_SHOWPREVIEW, 0)
	self.ActorSequences = {}
end

//****************************************************
//*	Assigns a valid sequence root node to this camera
//* node so that it can fire actor animations
function ENT:SetActorSequences(sequenceRootNodes)

	if sequenceRootNodes then //TODO: and checktype
		self.ActorSequences = sequenceRootNodes
	else
		self.ActorSequences = {}
	end

end

//****************************************************
//*	Enables camera node specific features to be removed
function ENT:OnDelete()

	local rotGrip = self:GetNWEntity(ANICAM_ROTGRIP)
	if self.BaseClass.IsValid(self,rotGrip) then rotGrip:Remove()	end

	local pathDirA = self:GetNWEntity(ID_PATH_DIRECTION_ENTITY_A)
	if self.BaseClass.IsValid(self,pathDirA) then pathDirA:Remove()	end
	local pathDirB = self:GetNWEntity(ID_PATH_DIRECTION_ENTITY_B)
	if self.BaseClass.IsValid(self,pathDirB) then pathDirB:Remove()	end
	
end

//****************************************************
//*	Enables display of the view finder
function ENT:SetPreview(previewData)

	local rootNode = self.BaseClass.GetRootNode(self)

	if self == rootNode then

		if previewData.ShowPreview then
			self:SetNWBool(ANICAM_SHOWPREVIEW, true)
			self:SetNWInt(ANICAM_PREVIEWSTATE, previewData.PreviewState)
		else
			self:SetNWBool(ANICAM_SHOWPREVIEW, false)
		end

	else
		rootNode:SetPreview(state)
	end

end

gPlayingCamera = nil

//****************************************************
//*	Enables the cameras parameters to be set/updated
function ENT:SetParameters(parameters)
	if parameters then
	

		//Message from client
		local rootNode = GetRootNode(self)
		if parameters.ShowPreview == 1 then

			 if gPlayingCamera and gPlayingCamera:IsValid() then
				gPlayingCamera:SetNWInt(ANICAM_SHOWPREVIEW, 0)
				gPlayingCamera:SetNWInt(ANICAM_PREVIEWSTATE, 0)
			 end
				 
			rootNode:SetNWInt(ANICAM_SHOWPREVIEW, 1)
			rootNode:SetNWInt(ANICAM_PREVIEWSTATE, parameters.PreviewState)
			rootNode:SetNWInt(ANICAM_SHOWCAMERAID,parameters.ShowFromCameraID)
			rootNode:SetNWInt(ANICAM_FRAMETYPE,parameters.FrameType)
			gPlayingCamera = rootNode

		else

			rootNode:SetNWInt(ANICAM_SHOWPREVIEW, 0)
			rootNode:SetNWInt(ANICAM_PREVIEWSTATE, -1)
			rootNode:SetNWInt(ANICAM_SHOWCAMERAID,parameters.ShowFromCameraID)
			rootNode:SetNWInt(ANICAM_FRAMETYPE,parameters.FrameType)
			gPlayingCamera = nil
		 end
		 
		self:SetNWInt(ANICAM_SELECTED, parameters.IsSelected)

		 
		self:SetNWInt(ANICAM_SHOWDIRECTION,parameters.IsShowDirection)
		self:SetNWInt(ANICAM_SHOWTANGENTS,parameters.IsShowTangents)
		rootNode:SetNWInt(ANICAM_SHOWTRACK,parameters.IsShowTrack)

		self:SetNWFloat(ANICAM_ZOOM,(170 - (1.7 * parameters.Zoom)))
		self:SetNWFloat(ANICAM_SHAKEAGRESSION,parameters.ShakeAgression)
		self:SetNWFloat(ANICAM_SHAKEFREQUENCY,parameters.ShakeFrequency)
		self:SetNWFloat(ANICAM_TIMETRANSITION,parameters.TimeTransition)
		self:SetNWFloat(ANICAM_TIMESTOP, parameters.TimeStop)

		local drawDirection = (self:GetNWInt(ANICAM_SHOWDIRECTION) == 1)
		self:GetNWEntity(ANICAM_ROTGRIP):SetNoDraw(drawDirection)

		 print("SETT PARAMS")
		 print("root ",rootNode)
		print(rootNode:GetNWInt(ANICAM_SHOWPREVIEW))
		print(rootNode:GetNWInt(ANICAM_PREVIEWSTATE))


	 end
end


//****************************************************
//* Sets the camera direction and associated grip
function ENT:SetLookAt(pos)
	if pos != nil then

		local directionGrip = self:GetNWEntity(ANICAM_ROTGRIP)
	
		directionGrip:SetPos(pos)

		local directionVec = pos - self:GetPos()
		directionVec:Normalize()
		self:SetAngles(directionVec:Angle())
	end
end

//****************************************************
//*	Called externally to assign an actor pathway to this
//* node on the camera track. Returns true if successful
function ENT:AssignActorPathwayToTrack(actorPathway)
		
	/*if not self.BaseClass.IsPathNode(self, actorPathway) then
		return false
	end

	self.NumPaths = self.NumPaths + 1	
	self.PathTable[actorPathway:EntIndex()] = actorPathway
	self:SetNWInt("VarNumPaths", self.NumPaths)
	self:SetNWInt("VarPathEntID", actorPathway:EntIndex())

	 print("Assigned ", self.NumPaths)
	 print("Node ID:" ,self.BaseClass.GetNodeIndex(self))
	return true*/
end

//****************************************************
//* Called internally, this function checks to see if 
//* there are any 'actor walking pathways' that have been
//* assigned to it. If any are discovered, they are
//* executed to cause respective actors to walk along 
//* those tracks
function ENT:ThinkActorPathways()

//print("function ENT:ThinkActorPathways()", self.BaseClass.GetNodeIndex(self))
//print("paths = ", self.PathTable)
//print("num paths = ", self.NumPaths)
	if (not self.PathTable) or self.NumPaths == 0 then
		return
	end
print("itterating...")
	for k, actorPathNode in pairs(self.PathTable) do
		//if self.BaseClass.IsPathNode(self, actorPathNode) then

		//	//Acording to this functions documentation
		//	//it is safe to call this function on any node
		//	//on the pathway track
		//	print("playing...")
		//	actorPathNode:PlayActors(0)

		//end
	end

end

function ENT:Think()


	self.Entity:NextThink(CurTime())
	//return

	//if self.IsMapController then return end


	//local masterController = self:GetNWEntity("MasterController")
	//if masterController and masterController.Playing then

	//end

	//if self:GetNWBool("IsMasterController") then
	//	if self.Playing and self.ViewPointEnt then
	//		self:GetPointData()
	//	local playerIndex = self.BaseClass.GetPlayerIndex(self)
	//	local trackIndex = self.BaseClass.GetTrackIndex(self)

	//	for key,node in pairs(CatmullRomCams.Tracks[playerIndex][trackIndex]) do

	//		local viewPointPosition = self.ViewPointEnt:GetPos()
	//		local nodePosition = node:GetPos()
	//		if viewPointPosition:Distance(nodePosition) < 10 then
	//			node:ThinkActorPathways()
	//			break
	//		end

	//	end


	//		//self:ThinkActorPathways()
	//		
	//		if #self.CatmullRomController.PointsList < 4 then
	//			self.ViewPointEnt:Remove()
	//			
	//			self.Playing = false
	//			self:SetNWBool("IsPlaying", false)
	//		end
	//	end
	//end

end

function ENT:OnChangeSegment(segment)

	print("Changing on camera track...")
	self:ThinkActorPathways()
	//self:CheckOutsideRange(segment)
	//self:CheckTriggerEvents(segment)

	if ent and ent:IsValid() and ent.OnNodeTriggerNumPadKey then
		local ply    = self:GetNetworkedEntity("ControllingPlayer")
		
		self:InternalQuickToggleNumpad(ent.OnNodeTriggerNumPadKey.Keys, ply, ply:UniqueID())
		
		if not ent.OnNodeTriggerNumPadKey.Hold then
			return timer.Simple(.25, self.InternalQuickToggleNumpad, self, ent.OnNodeTriggerNumPadKey.Keys, ply, ply:UniqueID())
		end
	end
end

function ENT:PhysicsUpdate(physobj)
	if not self.Entity:IsPlayerHolding() then
		if self.IsMapController then
			physobj:EnableMotion(false)
		else
			physobj:Sleep()
		end
	end
end
